local Tuntian = {}

--- 机制相关 ---

--- 判断牌是否明置
---@param card integer
---@return boolean
Tuntian.isShown = function (card)
  if Fk:getCardById(card):getMark(MarkEnum.ShownCards) > 0 then
    return true
  end

  if table.find(MarkEnum.TempMarkSuffix, function (suffix)
    return Fk:getCardById(card):getMark(MarkEnum.ShownCards..suffix) > 0
  end) then
    return true
  end

  return false
end

--- 轮椅相关 ---

-- A的体力向B调整
---@param from ServerPlayer @ A
---@param to ServerPlayer @ B
---@param num integer @ 调整数
---@param skill_name string @ 技能名
---@param proposer ServerPlayer @ 操作者
function Tuntian.adjustHpTo(from, to, num, skill_name, proposer)
  if from.hp == to.hp then return false end
  if from.hp > to.hp then
    from.room:loseHp(from, math.min(num, (from.hp - to.hp)), skill_name)
  else
    from.room:recover{
      who = from,
      num = math.min(num, (to.hp - from.hp)),
      skill_name = skill_name,
      recoverBy = proposer,
    }
  end
  return true
end

--- 角色调整手牌数（通过摸牌弃牌）
---@param player ServerPlayer @ 角色
---@param toNumber integer @ 目标手牌数
---@param skill_name string @ 技能名
---@param prompt string? @ 提示信息
---@param skip boolean? @ 是否跳过
---@return table<integer, integer[]> @ <手牌数变化量，因此移动的牌>
function Tuntian.adjustHandcardNumTo(player, toNumber, skill_name, prompt, skip)
  prompt = prompt or Fk:translate(skill_name) .. "：将手牌数调整至" .. tostring(toNumber)
  local room = player.room
  local cards = {}
  local orig = player:getHandcardNum()
  local diff = toNumber - orig
  if diff == 0 then return {0, {}} end
  if diff > 0 then
    cards = room:drawCards(player, diff, skill_name)
  else
    cards = room:askToDiscard(player, {
      min_num = math.abs(diff),
      max_num = math.abs(diff),
      skill_name = skill_name,
      cancelable = false,
      prompt = prompt,
      skip = skip,
    })
  end
  return {math.abs(diff), cards}
end

-- 直接触发一个技能的效果（OnUse）
---@param skill any @ 技能名或技能
---@param event TriggerEvent @ 触发事件
---@param target ServerPlayer @ 目标
---@param player ServerPlayer @ 执行者
---@param data any
---@return boolean? @
function Tuntian.triggerSkill(skill, event, target, player, data)
  if type(skill) == "string" then skill = Fk.skills[skill] end
  if not skill then return end
  local room = player.room ---@type Room
  room.current_cost_skill = skill

  room.logic:trigger(fk.BeforeTriggerSkillUse, player, { skill = skill, willUse = true })

  return room:useSkill(player, skill, function()
    return skill:use(event, target, player, data)
  end, {})
end

--- qml 相关 ---

--- 获取卡牌数据
---@param id integer
---@param room AbstractRoom
---@return table @ id, name, suit, color, number, from (general)
Tuntian.getCardData = function (id, room)
  local card = Fk:getCardById(id)
  return { id = id, name = card.name, suit = card:getSuitString(), color = card:getColorString(), number = card.number, from = room:getCardOwner(id).general }
end

-- 选场上的牌，参数：choices, all_choices, cids, fids
---@param spec table
Tuntian.CardNameBox = function (spec)
  spec.choices = type(spec.choices) == "table" and spec.choices or Util.DummyTable
  spec.all_choices = type(spec.all_choices) == "table" and spec.all_choices or spec.choices
  spec.default_choice = spec.choices[1]
  spec.type = "custom"
  spec.qml_path = "packages/tuntian_studio/qml/OnfieldCardName"
  return spec
end

--- 氯师杀适配相关 ---

--- 如果是氯师杀也有的牌，返回氯师杀的牌，否则返回原牌名
---@param card string @牌名
---@return string @牌名
Tuntian.cardFix = function (card)
  if Fk.all_card_types["lvshi__" .. card] then
    return "lvshi__" .. card
  end
  return card
end

return Tuntian